.section .text
__start:
    nop                       # PC = 0x00
    j csr_test                # PC = 0x04

error:
    mv x31, x1                # PC = 0x08
    j error                   # PC = 0x0C

success:
    addi x31, x31, 1          # PC = 0x10, x31++
    j success                 # PC = 0x14

csr_test:
    lw x2, 4(x0)              # PC = 0x18, x2 = 0x00000008
    lw x4, 8(x0)              # PC = 0x1C, x4 = 0x00000010
    lw x5, 12(x0)             # PC = 0x20, x5 = 0x00000014
    lw x6, 16(x0)             # PC = 0x24, x6 = 0xffff0000
    lw x7, 20(x0)             # PC = 0x28, x7 = 0x0fff0000

    # Test CSR instructions
    # csrrw / csrrwi
    csrrwi x1, mscratch, 0x10 # PC = 0x2C, CSR[8] = 0x00000010
    csrr x1, mscratch         # PC = 0x30, x1 = 0x00000010
    csrrw x2, mscratch, x6    # PC = 0x34, CSR[8] = 0xffff0000, x2 = 0x00000010
    csrr x1, mscratch         # PC = 0x38, x1 = 0xffff0000

    # csrrs / csrrc
    li x1, 0x30               # PC = 0x3C, x1 = 0x00000030
    csrrs x2, mscratch, x1    # PC = 0x40, CSR[8] = 0xffff0030, x2 = 0xffff0000
    csrr x1, mscratch         # PC = 0x44, x1 = 0xffff0030
    li x1, 0x20               # PC = 0x48, x1 = 0x00000020
    csrrc x2, mscratch, x1    # PC = 0x4C, CSR[8] = 0xffff0010, x2 = 0xffff0030
    csrr x1, mscratch         # PC = 0x50, x1 = 0xffff0010

    # csrrsi / csrrci
    csrrsi x2, mscratch, 0x18 # PC = 0x54, CSR[8] = 0xffff0018, x2 = 0xffff0010
    csrr x1, mscratch         # PC = 0x58, x1 = 0xffff0018
    csrrci x2, mscratch, 0x10 # PC = 0x5C, CSR[8] = 0xffff0008, x2 = 0xffff0018
    csrr x1, mscratch         # PC = 0x60, x1 = 0xffff0008

exception_interruption_test:
    # Setup Trap Handler
    la x1, _trap              # PC = 0x64, load _trap address to x1, x1=0x00000064
    # PC = 0x68, x1=0x000000c0 (la is actual two instructions: auipc + addi)
    csrw mtvec, x1            # PC = 0x6C, set mtvec to _trap, CSR[5] = 0x000000c0

ecall_test:
    ecall                     # PC = 0x70
    j illegal_inst_test       # PC = 0x74
    jal x1, error             # PC = 0x78
    jal x1, error             # PC = 0x7C
    jal x1, error             # PC = 0x80

illegal_inst_test:
    .word 0xffff0000          # PC = 0x84, 0xffff0000 is illegal instruction
    j load_test               # PC = 0x88
    jal x1, error             # PC = 0x8C
    jal x1, error             # PC = 0x90
    jal x1, error             # PC = 0x94

load_test:
    lw x1, 128(x31)           # PC = 0x98, load access fault
    j store_test              # PC = 0x9C
    jal x1, error             # PC = 0xA0
    jal x1, error             # PC = 0xA4
    jal x1, error             # PC = 0xA8

store_test:
    sw x1, 128(x31)           # PC = 0xAC, store access fault
    mv x31, x0                # PC = 0xB0, reset x31 to 0
    j success                 # PC = 0xB4
    jal x1, error             # PC = 0xB8
    jal x1, error             # PC = 0xBC

_trap:
    csrr x26, mepc            # PC = 0xC0, mepc    (1) 0x00000070 (2) 0x00000084 (3) 0x00000098 (4) 0x000000AC
    csrr x27, mcause          # PC = 0xC4, mcause  (1) 0x0000000b (2) 0x00000002 (3) 0x00000005 (4) 0x00000007 (5) 中断 0x8000000b
    csrr x28, mstatus         # PC = 0xC8, mstatus 0x00001880
    csrr x29, mtval           # PC = 0xCC, mtval   (1) 0x00000000 (2) 0xffff0000 (3) 0x00000080 (4) 0x00000080
    bltz x27, 1f              # PC = 0xD0, if mcause[31] == 1 (equivalent to mcause < 0), don't add 4 to mepc
    addi x26, x26, 4          # PC = 0xD4, x26     (1) 0x00000074 (2) 0x00000088 (3) 0x0000009C (4) 0x000000B0
1:  csrw mepc, x26            # PC = 0xD8
    mret                      # PC = 0xDC

    jal x1, error             # PC = 0xE0
    jal x1, error             # PC = 0xE4
    jal x1, error             # PC = 0xE8
